package io.eguan.vold.rest.resources; /* * #%L * Project eguan * %% * Copyright (C) 2012 - 2017 Oodrive * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import io.eguan.vold.jmx.client.JmxClientConnectionFactory; import io.eguan.vold.model.VvrManagerMXBean; import java.io.File; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.Query; import org.junit.runners.model.InitializationError; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Strings; import com.sun.tools.attach.AgentInitializationException; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; /** * Helper class for JMX-specific test utility methods. * * @author oodrive * @author pwehrle * */ public final class JmxTestHelper { private static final Logger LOGGER = LoggerFactory.getLogger(JmxTestHelper.class); /** * Gets the set of server URLs for all detected local MBean servers that have a registered MBeans of a given class * and/or a provided ObjectName. * * @param objName * the {@link ObjectName} to search for or <code>null</code> * @param className * the target class' canonical name or <code>null</code> * @return a possibly empty {@link Set} of valid server URLs * @throws NullPointerException * if the provided {@link ObjectName} is <code>null</code> */ public static final Set<String> getLocalMBeanServerUrls(final ObjectName objName, final String className) throws NullPointerException { final HashSet<String> result = new HashSet<String>(); final List<VirtualMachineDescriptor> javaVms = VirtualMachine.list(); final String mgmtAgentPath = System.getProperty("java.home") + String.format("%slib%smanagement-agent.jar", File.separator, File.separator); for (final VirtualMachineDescriptor currDescriptor : javaVms) { VirtualMachine currVm; try { currVm = VirtualMachine.attach(currDescriptor.id()); String connectorAddress = currVm.getAgentProperties().getProperty( "com.sun.management.jmxremote.localConnectorAddress"); if (connectorAddress == null) { try { currVm.loadAgent(mgmtAgentPath); connectorAddress = currVm.getAgentProperties().getProperty( "com.sun.management.jmxremote.localConnectorAddress"); } catch (AgentLoadException | AgentInitializationException e) { LOGGER.warn("Failed to load Management Agent on process " + currVm.id(), e); } } LOGGER.info("Connector address for PID=" + currDescriptor.id() + ": " + connectorAddress); if (connectorAddress == null) { continue; } final MBeanServerConnection conn = JmxClientConnectionFactory.newConnection(connectorAddress); final Set<ObjectInstance> response = conn.queryMBeans(objName, Strings.isNullOrEmpty(className) ? null : Query.isInstanceOf(Query.value(className))); if (response.size() > 0) { result.add(connectorAddress); } } catch (AttachNotSupportedException | IOException e) { LOGGER.error("Exception", e); } } return result; } private String serverUrl; /** * Returns the configured {@link javax.management.MBeanServer} URL. * * @return the serverUrl, <code>null</code> before {@link #setUp()} was called or for embedded * {@link javax.management.MBeanServer}s. */ final String getServerUrl() { return serverUrl; } /** * Sets up common fixture. * * @throws InitializationError * if setup fails */ public final void setUp() throws InitializationError { // set up fixture // gets a server URL from local process inspection final Set<String> serverUrls = getLocalMBeanServerUrls(null, VvrManagerMXBean.class.getCanonicalName()); if (!serverUrls.isEmpty()) { if (serverUrls.size() > 1) { throw new InitializationError("More than one target MBean servers found!"); } serverUrl = serverUrls.iterator().next(); } } /** * Tears down common fixture. */ public final void tearDown() { // tear down fixture } /** * Retrieves the owner {@link java.util.UUID} from the {@link VvrManagerMXBean}. * * @return a non-empty {@link String} of the owner UUID * @throws IllegalStateException * if querying the {@link VvrManagerMXBean} fails */ public final String resolveVvrOwnerUuid() throws IllegalStateException { if (serverUrl == null) { try { this.setUp(); } catch (final InitializationError e) { throw new IllegalStateException(e); } } MBeanServerConnection connection; Set<ObjectName> foundManagers; try { connection = JmxClientConnectionFactory.newConnection(serverUrl); foundManagers = connection.queryNames(null, Query.isInstanceOf(Query.value(VvrManagerMXBean.class.getCanonicalName()))); } catch (SecurityException | IOException e) { throw new IllegalStateException(e); } if (foundManagers.isEmpty()) { throw new IllegalStateException("No VvrManager found; serverUrl=" + serverUrl); } final VvrManagerMXBean vvrMgrProxy = JMX.newMXBeanProxy(connection, foundManagers.iterator().next(), VvrManagerMXBean.class); return vvrMgrProxy.getOwnerUuid(); } }